import 'dart:convert';
import 'dart:io';

import 'package:cookie_jar/cookie_jar.dart';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:flustars/flustars.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:nft_shop/login/controller/user_controller.dart';
import 'package:nft_shop/res/constant.dart';
import 'package:nft_shop/res/global.dart';
import 'package:nft_shop/util/log_utils.dart';

import 'api.dart';


String _key = "MINGYANGB7D0C9D279892857DE5490AB856772FE";
//测试环境 'https://api.kingtrader.shop/';
//正式 https://api.kingtrader.pro/
final Http http = Http();

class Http extends BaseHttp {
  @override
  void init() {
    options.baseUrl = Global.AppHost;
    // options.contentType =  Headers.formUrlEncodedContentType;
    interceptors
      ..add(LoggingInterceptor())
      ..add(CookieManager(CookieJar()))
      ..add(ApiInterceptor());
  }

  /// [e]分类Error和Exception两种
  String setError(e, stackTrace, {String? message}) {
    /// 见https://github.com/flutterchina/dio/blob/master/README-ZH.md#dioerrortype
    if (e is DioError) {
      if (e.type == DioErrorType.connectTimeout ||
          e.type == DioErrorType.sendTimeout ||
          e.type == DioErrorType.receiveTimeout) {
        message = e.error;
      } else if (e.type == DioErrorType.response) {
        // incorrect status, such as 404, 503...
        message = e.error;
      } else if (e.type == DioErrorType.cancel) {
        // to be continue...
        message = e.error;
      } else {
        // dio将原error重新套了一层
        e = e.error;
        if (e is UnAuthorizedException) {
          stackTrace = null;
        } else if (e is NotSuccessException) {
          stackTrace = null;
          message = e.msg;
        } else
        if (e is SocketException) {
          message = e.message;
        } else {
          message = e.message;
        }
      }
    }
    return message??"";
  }

}

/// 请求头
class ApiInterceptor extends InterceptorsWrapper {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    //当前时间戳
    late DateTime timestamp = new DateTime.now();
    options.headers['timestamp'] = timestamp.millisecondsSinceEpoch;

    Map<String,dynamic> sign = {"pathinfo":options.path,"domain":Global.AppHost,"key":_key,"timestamp":timestamp.millisecondsSinceEpoch,};
    if(options.path != "upimg"){
      if(options.method == "GET"&&ObjectUtil.isNotEmpty(options.queryParameters)){
        sign.addAll(options.queryParameters);
      }else if(options.method == "POST"&&ObjectUtil.isNotEmpty(options.data)){
        sign.addAll(options.data);
      }
    }
    options.headers['sign'] = toMD5(_objKeySort(sign));

    if (UserController.to.isLogin) {
      options.headers['token'] = UserController.to.token();
    }
    Log.d('RequestHeaders:${options.headers}');
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    // print('---api-response--->resp----->${response.data}');
    ResponseData respData = ResponseData.fromJson(response.data);
    if (respData.success) {
      // if(response.requestOptions.path=="v1/goodsPay" && response.requestOptions.data["pay_type"]==2) {
      //   response.data = respData;
      // }else {
        response.data = respData.data;
      // }
      super.onResponse(response, handler);
    } else {
      if (respData.code == 401 && respData.msg == "Token验证失败") {
        print("---退出登录了--");
        // 如果cookie过期,需要清除本地存储的登录信息
        // StorageManager.localStorage.deleteItem(UserModel.keyUser);
        throw UnAuthorizedException(); // 需要登录
      } else {
        EasyLoading.showToast(respData.msg??"");
      }
    }
  }

  //md5加密
  static String toMD5(String data) {
    var content = new Utf8Encoder().convert(data);
    var digest = md5.convert(content);
    return digest.toString();
  }
  //排序并拼接&
  String _objKeySort(Map<String,dynamic> obj){
    List<String> newkey = obj.keys.toList()..sort();
    String newObj = "";
    for (int i = 0; i < newkey.length; i++) {
      if(newObj.isNotEmpty){
        newObj = newObj+"&";
      }
      newObj =newObj+"${newkey[i]}=${obj[newkey[i]]}";
    }
    return newObj;
  }

}

//日志信息
class LoggingInterceptor extends Interceptor{

  late DateTime _startTime;
  late DateTime _endTime;

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    _startTime = DateTime.now();
    // Log.v('----------Start----------');
    // if (ObjectUtil.isEmpty(options.queryParameters)) {
      // Log.v('RequestUrl: ${options.baseUrl}${options.path}');
    // } else {
      Log.d('RequestUrl: ${options.baseUrl}${options.path}?${Transformer.urlEncodeMap(options.queryParameters)}');
    // }
    // Log.v('RequestMethod: ${options.method}');
    // Log.v('RequestHeaders:${options.headers}');
    // Log.d('RequestContentType: ${options.contentType}');
    if(options.method == "GET"&&ObjectUtil.isNotEmpty(options.queryParameters)){
      // Log.v('RequestData: ${options.queryParameters.toString()}');
    }else if(options.method == "POST"&&ObjectUtil.isNotEmpty(options.data)){
      // Log.v('RequestData: ${options.data.toString()}');
    }
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    _endTime = DateTime.now();
    final int duration = _endTime.difference(_startTime).inMilliseconds;
    if (response.statusCode == 201 || response.statusCode == 200) {
      // Log.v('ResponseCode: ${response.statusCode}');
    } else {
      // Log.e('ResponseCode: ${response.statusCode}');
    }
    // 输出结果
    Log.v(response.data.toString());
    // Log.v('----------End: $duration 毫秒----------');
    super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    Log.v('----------Error-----------${err.response!.requestOptions.path}');
    EasyLoading.dismiss();
    // EasyLoading.showToast('网络异常，请稍后再试');
    super.onError(err.error, handler);
  }
}


class ResponseData extends BaseResponseData {
  bool get success => 200 == code || 201 == code;

  ResponseData.fromJson(Map<String, dynamic> json) {
    code = json['code'];
    msg = json['msg'];
    data = json['data'];
  }
}
